﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Windows.Forms;
using QDSpider.manager;
using QDSpider.Models;
using QDSpider.Sogou;
using System.Text.RegularExpressions;
using System.Threading;
using MaterialSkin;
using Newtonsoft.Json;
using WeiTap.Web;

namespace QDSpider
{
    public partial class Main : BaseForm
    {
        private readonly MaterialSkinManager materialSkinManager;
        private static User _currentUser;
        private const string Keyurl =
           "http://weixin.sogou.com/weixin?query={0}&_sug_type_=&s_from=input&_sug_=y&type=2&page={1}&ie=utf8";

        private const string ProxyUrl = "http://admin.711688.com.cn/article/ProxyWXImg.ashx?url=";
        private const string AccUrl = "http://weixin.sogou.com/weixin?type=1&query={0}";
        public Main()
        {
            InitializeComponent();
            materialSkinManager = MaterialSkinManager.Instance;
            materialSkinManager.AddFormToManage(this);
            materialSkinManager.Theme = MaterialSkinManager.Themes.LIGHT;
            materialSkinManager.ColorScheme = new ColorScheme(Primary.Yellow800, Primary.Yellow900, Primary.Yellow500, Accent.LightBlue200, TextShade.WHITE);
            this.TxtMsg = this.txtMsg;
            var cache = DictionalHelper.ReadFirsKeyValuePair();
            if (cache.Equals(default(KeyValuePair<string, string>))) return;
            txtUserName.Text = cache.Key;
            txtUserPassword.Text = cache.Value;
        }


        private void Login()
        {
            AppendMsg("正在登陆");
            _currentUser = UserManager.Login(txtUserName.Text, txtUserPassword.Text);
            if (_currentUser == null)
            {
                AppendMsg("登陆失败!账号或者密码错误!");
                return;
            }
            DictionalHelper.Save(txtUserName.Text, txtUserPassword.Text);
            AppendMsg("登陆成功");

        }

        private void RequestFromKeyword(ArticleSetting settings)
        {
            var keys = settings.Keywords.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

            foreach (var key in keys)
            {
                GetArticleListKey(key);
            }

        }

        private void RequestFromAccount(ArticleSetting settings)
        {
            var accs = settings.Accounts.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            foreach (var acc in accs)
            {

                GetWeiChatAcountList(acc);
            }

        }

        private void RequestEnd(ArticleSetting settings)
        {
            settings.LastRequestTime = DateTime.Now;

            ArticleSettingManager.Update(settings);
        }

        /// <summary>
        /// 通过关键词搜索
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        private void GetArticleListKey(string key,int page = 1)
        {
            if (page == 1) AppendMsg($"正在采集关键词:{key}");
            try
            {
                var searchUrl = string.Format(Keyurl, System.Web.HttpUtility.UrlEncode(key), page);
                var helper = new JietuDAL.DateHelp();
                var ds = helper.Select();
                var www = new HttpFire(searchUrl) { Method = HttpRequestMethod.Get, AutoRedirect = true };
                www.Headers.AutoAddDefaultHeaders = true;
                www.Headers.Referer = "http://news.sogou.com/news?ie=utf8&p=40230447&query=KAMCHAFONG&";
                www.Headers.UserAgent =
                    "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36";
                if (ds != null && ds.Tables[0].Rows.Count > 0)
                {
                    var snuid = ds.Tables[0].Rows[0][0].ToString();
                    var suv = ds.Tables[0].Rows[0][1].ToString();

                    www.Cookies.Add(new Cookie("SNUID", snuid, "/", ".sogou.com"));
                    www.Cookies.Add(new Cookie("SUV", suv, "/", ".sogou.com"));
                }
                var htmlResult = www.GetString();
                Trace.TraceInformation(htmlResult);
                var doc = new HtmlAgilityPack.HtmlDocument();
                doc.LoadHtml(htmlResult);
                var newlist = doc.QuerySelectorAll(".news-list ul li");
                foreach (var node in newlist)
                {
                    var a = new Article();
                    var link = node.QuerySelector(".txt-box h3 a");
                    if (link == null) continue;
                    a.HtmlUrl = HttpUtility.HtmlDecode(link.Attributes["href"]?.Value ?? "");
                    a.Title = link.InnerText;
                    if (string.IsNullOrEmpty(a.Title)) continue;
                    a.Title = a.Title.Replace("<!--red_beg-->", "")?.Replace("<!--red_end-->", "") ?? "";
                    a.Title = HttpUtility.HtmlDecode(a.Title);
                    if (ArticleManager.Exist(a.Title, _currentUser.UserId))
                    {
                        AppendMsg($"成功采集文章:[{a.Title}]");
                        continue;
                    }
                    var img = node.QuerySelector(".img-box img");
                    Uri logoUri;
                    if (img != null)
                    {
                        var r = HttpUtility.HtmlDecode(img.Attributes["src"]?.Value ?? "");
                        if (!r.StartsWith("http")) r = "http:"+r;
                        Uri.TryCreate(r, UriKind.RelativeOrAbsolute, out logoUri);
                    }
                    else
                    {
                        var imgd = node.QuerySelectorAll(".txt-box .img-d img");
                        var r = HttpUtility.HtmlDecode(imgd?.FirstOrDefault()?.Attributes["src"]?.Value ?? "");
                        if (!r.StartsWith("http")) r = "http:" + r;
                        Uri.TryCreate(r, UriKind.RelativeOrAbsolute, out logoUri);
                    }
                    if (logoUri != null && logoUri.Host.Contains("sogoucdn"))
                    {
                        var query = logoUri.Query.TrimStart('?');
                        var rawUrl = query.Split('&').FirstOrDefault(t => t.StartsWith("url"))?.Split('=')[1];
                        a.Logo = rawUrl;
                    }
                    else if (logoUri != null) a.Logo = logoUri.ToString();

                    a.SourceId = 20;
                    a.Source = "用户自定义";
                    a.State = 5;

                    var p = node.QuerySelector(".s-p .s2 script");
                    var num2 = RegexFetch("([1-9]\\d*\\.?\\d*)|(0\\.\\d*[1-9])", p.InnerText);
                    long ticks = 0;
                    if (long.TryParse(num2, out ticks))
                    {
                        a.HtmlDate = new DateTime(1970, 1, 1).AddSeconds(ticks).ToString();
                    }

                    a.Date = DateTime.Now;
                    var copyRight = false;
                    a.Content = GetArticleContent(a.HtmlUrl, out copyRight);
                    if(string.IsNullOrEmpty(a.Content))continue;
                    a.CopyRight = copyRight;
                    a.CreateUserId = _currentUser.UserId;
                    a.CreateUserName = _currentUser.UserName;
                    ArticleManager.Insert(a);
                    AppendMsg($"成功采集文章:{a.Title}");
                }
                var m = doc.QuerySelector("div .mun")?.InnerText.Remove(0, 3);
                m = m?.Substring(0, m.IndexOf("条", StringComparison.OrdinalIgnoreCase)).Replace(",", "");
                var maxRecord = 1;
                var maxPage = 1;
                if (int.TryParse(m, out maxRecord))
                {
                    if (maxRecord > 100) maxPage = 10;
                    else
                        maxPage = maxRecord / 10 + 1;
                }
                if (page < maxPage)
                    GetArticleListKey(key,page + 1);
                if(page==1)AppendMsg($"关键词采集结束");

            }
            catch (Exception e)
            {
                Trace.TraceError(e.Message);
                AppendMsg(e.Message);
                throw;
            }


        }
        /// <summary>
        /// 获取搜狗微信公众号，以及请求地址
        /// </summary>
        /// <param name="account"></param>
        /// <returns></returns>
        private void GetWeiChatAcountList(string account)
        {
            if (!CheckChatAccount(account)) return;
            AppendMsg($"正在采集公众号:[{account}]");
            var searchUrl = string.Format(AccUrl, HttpUtility.UrlEncode(account));
            var accountUrl = GetWeiChatAccountUrl(searchUrl, account);
            if (string.IsNullOrEmpty(accountUrl)) { AppendMsg($"公众号{account}不存在"); return; }
            GetArticleList(accountUrl, account);
            GetWeiCharAccountListEnd(account);

        }

        private bool CheckChatAccount(string account)
        {
            var his = ArticleAccountFetchHistoryManager.Get(_currentUser.UserId, account);
            if (his == null) return true;
            if (his.LastRequestTime.Date != DateTime.Now.Date) return true;
            AppendMsg($"公众号【{account}】采集成功");
            return false;
        }
        private void GetWeiCharAccountListEnd(string account)
        {
            var his = new ArticleAccountFetchHistory()
            {
                UserId = _currentUser.UserId,
                Account = account,
                LastRequestTime = DateTime.Now
            };
            ArticleAccountFetchHistoryManager.Insert(his);
        }
        private string GetWeiChatAccountUrl(string requestUrl, string accountCode)
        {
            var href = "";
            var helper = new JietuDAL.DateHelp();
            var ds = helper.Select();
            var www = new HttpFire(requestUrl) { Method = HttpRequestMethod.Get, AutoRedirect = true };
            www.Headers.AutoAddDefaultHeaders = true;
            www.Headers.Referer = "http://news.sogou.com/news?ie=utf8&p=40230447&query=KAMCHAFONG&";
            www.Headers.UserAgent =
                "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36";
            if (ds != null && ds.Tables[0].Rows.Count > 0)
            {
                var snuid = ds.Tables[0].Rows[0][0].ToString();
                var suv = ds.Tables[0].Rows[0][1].ToString();
                www.Cookies.Add(new Cookie("SNUID", snuid, "/", ".sogou.com"));
                www.Cookies.Add(new Cookie("SUV", suv, "/", ".sogou.com"));
            }
            var htmlResult = www.GetString();

            if (htmlResult == null)
            {
                AppendMsg("获取公众号链接失败，请稍后再试");
                return string.Empty;
            }


            int reloadTimes = 3;//尝试三次输入验证码
            while (htmlResult.Contains("您的访问过于频繁") && reloadTimes > 0)
            {
                AppendMsg($"搜索公众号出现验证码!");
                Process.Start("iexplore.exe", requestUrl);
                AppendMsg($"请在30秒内输入验证码,您还有{reloadTimes}次机会");
                Thread.Sleep(30000);
                htmlResult = www.GetString();
                reloadTimes--;
            }
            if (htmlResult.Contains("您的访问过于频繁"))
            {
                AppendMsg("您的访问过于频繁");
                return string.Empty;
            }
            var doc = new HtmlAgilityPack.HtmlDocument();
            doc.LoadHtml(htmlResult);
            var accountNode = doc.DocumentNode.SelectSingleNode("//*[@class=\"news-box\"]/ul/li[1]/div[1]/div[2]/p[2]/label[1]");
            var accountHref = doc.DocumentNode.SelectSingleNode("//*[@class=\"news-box\"]/ul/li[1]/div[1]/div[2]/p[1]/a[1]");
            var account = accountNode?.InnerText.Trim();
            var accountname = accountHref?.InnerText.Replace("<!--red_beg-->", "").Replace("<!--red_end-->", "").Trim();
            if (accountCode != accountname && accountCode != account) return string.Empty;//既不是公众号，也不是微信号
            href = accountHref?.Attributes["href"].Value;
            return HttpUtility.HtmlDecode(href);
        }
        private void GetArticleList(string requestUrl, string accountcode)
        {
            try
            {
                var www = new HttpFire(requestUrl) { Method = HttpRequestMethod.Get, AutoRedirect = true };

                var htmlResult = www.GetString();

                var reloadTimes = 3;//尝试三次输入验证码

                while (htmlResult.Contains("为了保护你的网络安全，请输入验证码") && reloadTimes > 0)
                {
                    var cert = DateTime.Now.Ticks.ToString() + new Random().NextDouble().ToString("0.0000");
                    var imgSrc = "http://mp.weixin.qq.com/mp/verifycode?cert=" + cert;
                    Process.Start("iexplore.exe", requestUrl);
                    AppendMsg($"请在30秒内输入验证码,您还有{reloadTimes}次机会");
                    Thread.Sleep(30000);
                    htmlResult = www.GetString();
                    reloadTimes--;
                }
                var reg = new Regex("msgList = {([\\s\\S]+?)};");
                var match = reg.Match(htmlResult);
                if (!match.Success) return;
                var jsonString = match.Value.Substring(9).TrimEnd(';');
                var model = JsonConvert.DeserializeObject<SougouWeiChatModel>(jsonString);
                if (model == null) return;
                foreach (var item in model.list)
                {
                    var htmlDate = new DateTime(1970, 1, 1).AddSeconds(item.comm_msg_info.datetime).ToString("yyyy-MM-dd HH:mm");
                    var article = new Article
                    {
                        SourceId = 20,
                        Source = "用户自定义",
                        Date = DateTime.Now,
                        Title = item.app_msg_ext_info.title,
                        Logo = ProxyUrl + item.app_msg_ext_info.cover,
                        HtmlUrl = item.app_msg_ext_info.content_url
                    };

                    article.HtmlUrl = "http://mp.weixin.qq.com" + WebRequestHelper.ReplaceHtml(article.HtmlUrl);
                    article.State = 5;
                    var copy = false;
                    article.Content = GetArticleContent(article.HtmlUrl, out copy);
                    if (string.IsNullOrEmpty(article.Content)) continue;
                    article.CopyRight = copy;
                    article.HtmlDate = htmlDate;
                    article.CreateUserId = _currentUser.UserId;
                    article.CreateUserName = _currentUser.UserName;
                    if (!ArticleManager.Exist(article.Title, article.CreateUserId))
                        ArticleManager.Insert(article);
                    AppendMsg($"成功采集文章:[{article.Title}]");
                    foreach (var msg in item.app_msg_ext_info.multi_app_msg_item_list)
                    {
                        msg.title = HttpUtility.HtmlDecode(msg.title);
                        article = new Article
                        {
                            SourceId = 20,
                            Source = "用户自定义",
                            Date = DateTime.Now,
                            Title = msg.title,
                            Logo = ProxyUrl + msg.cover,
                            HtmlUrl = msg.content_url
                        };

                        article.HtmlUrl = "http://mp.weixin.qq.com" + WebRequestHelper.ReplaceHtml(article.HtmlUrl);
                        article.State = 5;
                        var copyright = false;
                        article.Content = GetArticleContent(article.HtmlUrl, out copyright);
                        if(string.IsNullOrEmpty(article.Content))continue;
                        article.HtmlDate = htmlDate;
                        article.CreateUserId = _currentUser.UserId;
                        article.CreateUserName = _currentUser.UserName;
                        if (!ArticleManager.Exist(article.Title, article.CreateUserId))
                            ArticleManager.Insert(article);
                        AppendMsg($"成功采集文章:[{article.Title}]");
                    }
                }
                AppendMsg($"公众号采集结束");
            }
            catch (Exception e)
            {
                Trace.TraceError(e.Message);
                throw;
            }
        }
        private static string RegexFetch(string pattern, string input)
        {
            var g = new Regex(pattern);
            return !g.IsMatch(input) ? string.Empty : g.Matches(input)[0].Value;
        }
        private static string GetArticleContent(string requestUrl, out bool copyright)
        {
            WebRequestHelper.Referer = requestUrl;
            WebRequestHelper.Host = "mp.weixin.qq.com";
            var htmlResult = WebRequestHelper.Request(requestUrl);
            var reg = new Regex("js_content([\\s\\S]+?)</div>");
            var copy = new Regex("id=\"copyright_logo\"");
            var copyMath = copy.Match(htmlResult);
            copyright = copyMath.Success;
            var match = reg.Match(htmlResult);
            if (!match.Success) return string.Empty;
            try
            {
                var result = match.Value.Substring(13);
                result = result.Substring(0, result.Length - 6);
                result = result.Replace("data-src", "src");
                var eva = new MatchEvaluator(WordScrambler);
                result = Regex.Replace(result, "<img[^<>]*?\\ssrc=['\"]?(.*?)['\"].*?>", eva);
                var eva2 = new MatchEvaluator(WordScramblerBackground);
                result = Regex.Replace(result, "background-image:\\s*url\\([^\\s]*\\)", eva2);
                return result;
            }
            catch (Exception e)
            {
                return string.Empty;
            }
           
        }
        private static string WordScramblerBackground(Match match)
        {
            string img = match.Value;
            bool flag = img.IndexOf("base64", StringComparison.OrdinalIgnoreCase) > 0;
            string result;
            if (flag)
            {
                result = img;
            }
            else
            {
                string url = img.Substring(img.IndexOf("&quot;", StringComparison.OrdinalIgnoreCase) + 6);
                try
                {
                    string realUrl = ProxyUrl + url;
                    result = (string.IsNullOrEmpty(url) ? img : img.Replace(url, realUrl));
                }
                catch (Exception e)
                {
                    Trace.TraceError(e.Message);
                    throw;
                }
            }
            return result;
        }
        private static string WordScrambler(Match match)
        {
            var url = match.Groups[1].Value;
            var img = match.Value;
            var realUrl = ProxyUrl + url;
            return string.IsNullOrEmpty(url) ? string.Empty : img.Replace(url, realUrl);
        }


        private void btnRequest_Click(object sender, EventArgs e)
        {
            try
            {
                Login();
                if (_currentUser == null) return;
                var settings = ArticleSettingManager.GetByUserId(_currentUser.UserId);
                if (settings == null)
                {
                    AppendMsg("请前往http://www.711688.net.nc进行监控设置");
                    return;
                }
                //var ticks = DateTime.Now.Ticks - settings.LastRequestTime.Ticks;
                //if (TimeSpan.FromTicks(ticks).TotalMinutes < 60)
                //{
                //    AppendMsg("距离上次成功获取不足一个小时，请稍后再试!");
                //    return;
                //}
                RequestFromKeyword(settings);
                RequestFromAccount(settings);
                RequestEnd(settings);

            }
            catch (Exception ex)
            {
                AppendMsg(ex.Message);
            }
        }
    }

}
